/* Copyright 2013 (C) FatalEror / Dean Bahari
 * 
 * MainClient is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * See LICENSE file in main folder for more information.
 */

package jrock;

import java.nio.FloatBuffer;
import jrock.gui.*;
import jrock.filesystem.*;
import jrock.other.*;

import static org.lwjgl.opengl.GL11.*;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

/**
 * @author FatalEror
 */
public class MainClient {
    
    private boolean     polyMode          = false;
    private FloatBuffer matrixOrthogonal  = BufferUtils.createFloatBuffer(16);
    private FloatBuffer matrixPerspective = BufferUtils.createFloatBuffer(16);
    
    private long getTime() {
        return (Sys.getTime() * 1000) / Sys.getTimerResolution();
    }
    
    private void handleCamera(Camera cam) {
        final float movCam   = 0.2f;
        final float movSpeed = 0.02f;
        
        cam.yaw(Mouse.getDX() * movCam);
        cam.pitch(-Mouse.getDY() * movCam);
        
        if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
            cam.walkForward(movSpeed);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
            cam.walkBackward(movSpeed);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            cam.strafeLeft(movSpeed);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
            cam.strafeRight(movSpeed);
        }
    }
    
    public void start() {
        GRF grf = new GRF();
        grf.open("data.grf");
        
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.create();
        } catch (LWJGLException ex) {
            Logger.getLogger(MainClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        {
            double width, height;
            double zNear = 0.01;
            double zFar  = 1.0;
            height = Math.tan(Math.PI / 4) * zNear;
            width  = height * (800.0 / 600.0);
            
            glFrustum(-width, width, -height, height, zNear, zFar);
        }
        glGetFloat(GL_PROJECTION_MATRIX, matrixPerspective);
        glLoadIdentity();
        glOrtho(0.0f, 800.0f, 600.0f, 0.0f, 0.0f, 1.0f);
        glGetFloat(GL_PROJECTION_MATRIX, matrixOrthogonal);
        
        glShadeModel(GL_SMOOTH);
        glClearDepth(1.0);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_SMOOTH);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDepthFunc(GL_LEQUAL);
        glAlphaFunc(GL_GREATER, 0.0f);
        glEnable(GL_ALPHA_TEST);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        
        Mouse.setGrabbed(true);
        
        Matrix4f matrix = new Matrix4f();
        matrix.setIdentity();
        matrix.scale(new Vector3f(-0.001f, -0.001f, 0.001f));
        
        Camera cam = new Camera();
        cam.setTransform(matrix);
        
        RSW rsw = grf.getRSW("prt_fild00.rsw");
        
        long    lastFrame = getTime();
        long    fps       = 0;
        boolean finish    = false;
        while (!finish) {
            glMatrixMode(GL_PROJECTION);
            glLoadMatrix(matrixPerspective);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
            handleCamera(cam);
            cam.view();
            cam.setCamDef(new Vector3f(0.0f, 1.0f, 0.0f));
            
            while (Keyboard.next()) {
                if (Keyboard.getEventKeyState()) {
                    if (Keyboard.getEventKey() == Keyboard.KEY_P) {
                        if (!polyMode) {
                            polyMode = true;
                            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                        } else {
                            polyMode = false;
                            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                        }
                    }
                    if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
                        finish = true;
                    }
                }
            }
            
            glEnable(GL_TEXTURE_2D);
            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glColor3f(1.0f, 1.0f, 1.0f);
            rsw.draw(cam);
            glDisableClientState(GL_VERTEX_ARRAY);
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            glDisable(GL_TEXTURE_2D);
            
            glMatrixMode(GL_PROJECTION);
            glLoadMatrix(matrixOrthogonal);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            
            
            
            Display.update();
            
            fps++;
            if (getTime() > lastFrame) {
                Display.setTitle("FPS: " + fps);
                lastFrame += 1000;
                fps = 0;
            }
        }
        
        rsw.destroy();
        Display.destroy();
        
        grf.close();
    }
    
    public static void main(String[] args) {
        MainClient jrock = new MainClient();
        jrock.start();
    }
}
